package com.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;

import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.archivers.ar.ArArchiveEntry;
import org.apache.commons.compress.archivers.ar.ArArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
import org.apache.commons.compress.compressors.z.ZCompressorInputStream;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.lang.StringUtils;

import com.alibaba.fastjson.JSONObject;

public class ZipUtils {
    public static String[] ICON_TYPES = new String[] { "svg", "png", "jpg", "jpeg", "bmp" };

    /**
     * *解压deb文件并读取应用配置
     * 
     * @param inputDeb
     * @return
     * @throws IOException
     * @throws ArchiveException String
     */
    private static String unpackAndRead(String inputDeb) throws IOException, ArchiveException {
        String outputDir = "F:/temp/";
        String ret = StringUtils.EMPTY;
        // 创建临时目录
        createDirectory(outputDir, null);

        // 第一步,解压ar
        InputStream is = new FileInputStream(inputDeb);
        ArArchiveInputStream debInputStream = (ArArchiveInputStream) new ArchiveStreamFactory()
                .createArchiveInputStream("ar", is);
        ArArchiveEntry entry = null;
        String controlTarUrl = "";
        String dataTarUrl = "";

        while ((entry = (ArArchiveEntry) debInputStream.getNextEntry()) != null) {
            File outputFile = new File(outputDir, entry.getName());
            OutputStream outputFileStream = new FileOutputStream(outputFile);
            IOUtils.copy(debInputStream, outputFileStream);

            outputFileStream.close();

            if (StringUtils.contains(entry.getName(), "control.tar")) {
                controlTarUrl = outputFile.getAbsolutePath();
            }
            if (StringUtils.contains(entry.getName(), "data.tar")) {
                dataTarUrl = outputFile.getAbsolutePath();
            }
        }

        debInputStream.close();

        // 获取control配置信息
        if (StringUtils.isNotBlank(controlTarUrl)) {
            // 解压control.tar
            decompressTar(outputDir + "control/", controlTarUrl);
            // 读取control信息
            JSONObject read = read(outputDir + "control/control", ":");
            ret = read.toJSONString();
        }

        // 处理图标
        if (StringUtils.isNotBlank(dataTarUrl)) {
            // 解压data.tar
            decompressTar(outputDir + "data/", dataTarUrl);
            // 查找desktop文件
            String iconUrl = findIconUrlInDesktop(outputDir + "data/");
            if (StringUtils.isNotBlank(iconUrl)) {

                if (isFileUrl(iconUrl)) {
                    // 完整路径
                    System.out.println(outputDir + "data/" + iconUrl);
                    copy(outputDir + "data/" + iconUrl, new File(inputDeb).getParent());

                } else {
                    // 查找ICON文件
                    String iconName = iconUrl;
                    String svgurl = findIcon(outputDir + "data/", iconName);
                    if (StringUtils.isNotBlank(svgurl)) {
                        System.out.println(svgurl);
                        copy(svgurl, new File(inputDeb).getParent());
                    }
                }
            }
        }

        // 删除临时目录
        delFile(outputDir);

        return ret;

    }

    /**
     * *判断是否为文件完整路径
     * 
     * @param url
     * @return boolean
     */
    public static boolean isFileUrl(String url) {
        return StringUtils.contains(url, "/") || StringUtils.contains(url, "\\");
    }

    /**
     * *获取url上面的最后部分，也就是文件名+文件后缀
     * 
     * @param url
     * @return String
     */
    public static String getUrlName(String url) {
        String iconFileName = StringUtils.substringAfterLast(url, "/");
        if (StringUtils.isBlank(iconFileName)) {
            iconFileName = StringUtils.substringAfterLast(url, "\\");
        }

        return iconFileName;
    }

    /**
     * *将指定文件复制到指定的输出目录,名称不变
     * 
     * @param fileUrl
     * @param outputDir void
     */
    public static void copy(String fileUrl, String outputDir) {
        String filename = getUrlName(fileUrl);
        try {
            FileOutputStream outputStream = new FileOutputStream(outputDir + File.separator + filename);
            FileInputStream inputStream = new FileInputStream(new File(fileUrl));

            // copy到文件路径
            IOUtils.copy(inputStream, outputStream);

            if (inputStream != null) {
                inputStream.close();
            }

            if (outputStream != null) {
                outputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * *指定目录下查找ICON文件，返回绝对路径
     * 
     * @param dir
     * @param targetName
     * @return String
     */
    public static String findIcon(String dir, String iconName) {

        File file = new File(dir);
        if (!file.exists()) {
            return null;
        }

        if (file.isFile()) {
            // 判断文件名
            String fileName = file.getName();

            // 直接匹配
            if (StringUtils.equals(fileName, iconName)) {
                return file.getAbsolutePath();
            }
            // 加上后缀匹配
            for (int i = 0; i < ICON_TYPES.length; i++) {
                String type = ICON_TYPES[i];
                if (StringUtils.equals(fileName, iconName + "." + type)) {
                    return file.getAbsolutePath();
                }
            }
        } else {
            String[] filenames = file.list();
            for (String f : filenames) {
                String findDesktop = findIcon(dir + File.separator + f, iconName);
                if (StringUtils.isNotBlank(findDesktop)) {
                    return findDesktop;
                }
            }
        }

        return null;
    }

    /**
     * *查找desktop配置文件中ICON配置
     * 
     * @param dir 在该目录下找desktop文件
     * @return String
     */
    public static String findIconUrlInDesktop(String dir) {

        File file = new File(dir);
        if (!file.exists()) {
            return null;
        }

        if (file.isFile()) {
            // 判断文件名
            String fileName = file.getName();
            if (StringUtils.contains(fileName, ".desktop")) {
                // 打开文件,获取icon字段
                try {
                    JSONObject content = read(dir, "=");
                    String iconUrl = content.getString("Icon");
                    if (StringUtils.isNotBlank(iconUrl)) {
                        return iconUrl;
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } else {
            String[] filenames = file.list();
            for (String f : filenames) {
                String findDesktop = findIconUrlInDesktop(dir + File.separator + f);
                if (StringUtils.isNotBlank(findDesktop)) {
                    return findDesktop;
                }
            }
        }

        return null;
    }

    /**
     * *适配解压方式
     * 
     * @param tarPath
     * @return TarArchiveInputStream
     */
    public static TarArchiveInputStream getTarInputStream(String tarPath) {
        try {
            if (StringUtils.contains(tarPath, "gz")) {
                return new TarArchiveInputStream(new GzipCompressorInputStream(new FileInputStream(tarPath)));
            }

            if (StringUtils.contains(tarPath, "bz2")) {
                return new TarArchiveInputStream(new BZip2CompressorInputStream(new FileInputStream(tarPath)));
            }

            if (StringUtils.contains(tarPath, "xz")) {
                return new TarArchiveInputStream(new XZCompressorInputStream(new FileInputStream(tarPath)));
            }

            if (StringUtils.contains(tarPath, "Z")) {
                return new TarArchiveInputStream(new ZCompressorInputStream(new FileInputStream(tarPath)));
            }

            return new TarArchiveInputStream(new FileInputStream(tarPath));

        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * *文件解压到指定目录
     * 
     * @param outputDir
     * @param inputDir
     * @throws IOException void
     */
    public static void decompressTar(String outputDir, String inputDir) throws IOException {

        TarArchiveInputStream tarIn = getTarInputStream(inputDir);
        if (tarIn == null) {
            return;
        }
        createDirectory(outputDir, null);
        TarArchiveEntry entry;
        while ((entry = tarIn.getNextTarEntry()) != null) {
            if (entry.isDirectory()) {
                createDirectory(outputDir, entry.getName());
            } else {
                try {
                    OutputStream out = new FileOutputStream(new File(outputDir + File.separator + entry.getName()));
                    IOUtils.copy(tarIn, out);
                    out.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        tarIn.close();

    }

    /**
     * *创建目录
     *
     * @param outputDir
     * @param subDir
     */
    public static void createDirectory(String outputDir, String subDir) {
        File file = new File(outputDir);
        // 子目录不为空
        if (!(subDir == null || subDir.trim().equals(""))) {
            file = new File(outputDir + File.separator + subDir);
        }
        if (!file.exists()) {
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            file.mkdirs();
        }
    }

    /**
     * *删除文件
     * 
     * @param filename
     * @return boolean
     */
    static boolean delFile(String filename) {
        File file = new File(filename);
        if (!file.exists()) {
            return false;
        }

        if (file.isFile()) {
            return file.delete();
        } else {
            String[] filenames = file.list();
            for (String f : filenames) {
                delFile(filename + File.separator + f);
            }
            return file.delete();
        }
    }

    /**
     * *读取文件内容2字符串,封装到json对象返回
     * 
     * @param path 文件路径
     * @param sep 分隔符(key:value)
     * @return
     * @throws IOException JSONObject
     */
    private static JSONObject read(String path, String sep) throws IOException {

        FileInputStream inStream = new FileInputStream(path);
        BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));

        JSONObject info = new JSONObject();
        String input;
        String key = StringUtils.EMPTY;
        String value = StringUtils.EMPTY;
        while ((input = reader.readLine()) != null) {
            if (StringUtils.contains(input, sep)) {
                if (StringUtils.isNotBlank(key)) {
                    // 结束上一个匹配
                    info.put(key, value);
                }

                String[] split = StringUtils.split(input, sep, 2);
                if (split != null && split.length >= 2) {
                    key = split[0].trim();
                    value = split[1].trim();
                }
            } else {
                // 当前行是连着上一行value的
                value += input;
            }
        }

        // 将最后的key/value封装到JSON
        info.put(key, value);

        // 关闭流
        if (reader != null) {
            reader.close();
        }

        return info;
    }

    public static void main(String[] args) throws Exception {
        // // 完整路径
        // unpackAndRead("C:\\Users\\Justsafe-Zhonglj\\Downloads\\linuxqq_2.0.0-b1-1024_amd64.deb");
        // 无applications
        // String unpackAndRead =
        // unpackAndRead("C:\\Users\\Justsafe-Zhonglj\\Downloads\\fcitx-ui-qimpanel_1.1.0-0ubuntu1_amd64.deb");
        // System.out.println(unpackAndRead);
        // xxx
        String unpackAndRead = unpackAndRead(
                "C:\\Users\\Justsafe-Zhonglj\\Downloads\\accountsservice_0.6.55-0ubuntu10_amd64.deb");
        System.out.println(unpackAndRead);
        // // xxx.png
        // unpackAndRead("C:\\Users\\Justsafe-Zhonglj\\Downloads\\youker-assistant_2.2.7_ubuntu16.04.1_i386.deb");
        // String unpackAndRead = unpackAndRead(
        // "C:\\Users\\Justsafe-Zhonglj\\Downloads\\sogoupinyin_2.3.1.0112_amd64.deb");
        // System.out.println(unpackAndRead);
    }
}
